#include "processfile.h"
#include "Separator.h"
using namespace std;
//constants
const double twopi = 6.2831853071795864;


// global variables
// OK since we're making a standalone app
//icstdsp::AudioFile inputFile, outputFile;
Helmholtz* helmholtz = NULL;
//sigmundcpp *sigmund = NULL;
double phase_Hel = 0.; // phase of the sine wave. will be incremented on each sample
double phase_Sig = 0.; // phase of the sine wave. will be incremented on each sample
float *hhout = NULL; // buffer where we'll put the audio rate output of helmholtz
float initialFrequency = 1000.f;
float *sinBuffer_Hel = NULL; // array to write sine wave
float *sinBuffer_Sig = NULL; // array to write sine wave
float *pitchGraph_Hel =  NULL; // array to write graph
float *pitchGraph_Sig = NULL; // array to write graph
uint32_t sinIndex = 0; // index to write sine wave
uint32_t analysisChannel = 0;
float hold_freq = 1000;
float sum;
int times;
float *freq_array = NULL;
float *freq_array_Sig = NULL;
int num_freq = 0;
int num_freq_Sig = 0;
int blockSize = 0;
int *freq_array_rounded = NULL;
int num_freq_rounded = 0;
float avg_frequency_hel = 0;
float avg_frequency_sig = 0;
int channel = 0; //channel config here
Preferences* configPre = NULL;

int fileIndex = 0;
double freqchart[] = {
	8.1757989156, 8.661957218, 9.1770239974, 10.3008611535, 10.3008611535, 10.9133822323, 11.5623257097, 12.2498573744, 12.9782717994, 13.75, 14.5676175474, 15.4338531643,
	16.3515978313, 17.3239144361, 18.3540479948, 19.4454364826, 20.6017223071, 21.8267644646, 23.1246514195, 24.4997147489, 25.9565435987, 27.5, 29.1352350949, 30.8677063285,
	32.7031956626, 34.6478288721, 36.7080959897, 38.8908729653, 41.2034446141, 43.6535289291, 46.249302839, 48.9994294977, 51.9130871975, 55, 58.2704701898, 61.735412657,
	65.4063913251, 69.2956577442, 73.4161919794, 77.7817459305, 82.4068892282, 87.3070578583, 92.4986056779, 97.9988589954, 103.826174395, 110, 116.5409403795, 123.470825314,
	130.8127826503, 138.5913154884, 146.8323839587, 155.563491861, 164.8137784564, 174.6141157165, 184.9972113558, 195.9977179909, 207.65234879, 220, 233.081880759, 246.9416506281,
	261.6255653006, 277.1826309769, 293.6647679174, 311.1269837221, 329.6275569129, 349.228231433, 369.9944227116, 391.9954359817, 415.3046975799, 440, 466.1637615181, 493.8833012561,
	523.2511306012, 554.3652619537, 587.3295358348, 622.2539674442, 659.2551138257, 698.456462866, 739.9888454233, 783.9908719635, 830.6093951599, 880, 932.3275230362, 987.7666025122,
	1046.5022612024, 1108.7305239075, 1174.6590716696, 1244.5079348883, 1318.5102276515, 1396.912925732, 1479.9776908465, 1567.981743927, 1661.2187903198, 1760, 1864.6550460724, 1975.5332050245,
	2093.0045224048, 2217.461047815, 2349.3181433393, 2489.0158697766, 2637.020455303, 2793.825851464, 2959.9553816931, 3135.963487854, 3322.4375806396, 3520, 3729.3100921447, 3951.066410049,
	4186.0090448096, 4434.92209563, 4698.6362866785, 4978.0317395533, 5274.0409106059, 5587.6517029281, 5919.9107633862, 5919.9107633862, 6644.8751612791, 7040, 7458.6201842894, 7902.132820098,
	8372.0180896192, 8869.8441912599, 9397.272573357, 9956.0634791066, 10548.0818212118, 11175.3034058561, 11839.8215267723, 12543.853951416
};
char * midichart[] = {
	"C-2", "C#-2", "D-2", "D#-2", "E-2", "F-2", "F#-2", "G-2", "G#-2", "A-2", "A#-2", "B-2",
	"C-1", "C#-1", "D-1", "D#-1", "E-1", "F-1", "F#-1", "G-1", "G#-1", "A-1", "A#-1", "B-1",
	"C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "G#0", "A0", "A#0", "B0",
	"C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1",
	"C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2",
	"C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3",
	"C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4",
	"C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5",
	"C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6",
	"C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7",
	"C8", "C#8", "D8", "D#8", "E8", "F8", "F#8", "G8",
	"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
	"12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
	"24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35",
	"36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47",
	"48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
	"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71",
	"72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83",
	"84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95",
	"96", "97", "98", "99", "100", "101", "102", "103", "104", "105", "106", "107",
	"108", "109", "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
	"120", "121", "122", "123", "124", "125", "126", "127"
};

int compare(const void * a, const void *b){
	int c = *(int *)a;
	int d = *(int *)b;
	return c - d;
}
void sort_freq_array_rounded(){
	qsort(freq_array_rounded, num_freq_rounded, sizeof(freq_array_rounded[0]), compare);
}
int appear_the_most(){
	int hold = 0;
	int i = 0;
	int max = 0;
	while (i < num_freq_rounded - 1){
		int count = 0;
		while (freq_array_rounded[i] == freq_array_rounded[i + 1]){
			i++;
			count++;
		}
		if (max < count){
			max = count;
			hold = freq_array_rounded[i - 1];
		}
		i++;
	}
	return hold;
}
float new_avg(){
	int most = 0;
	if (initialFrequency != 0)
		most = initialFrequency;
	else
		most = appear_the_most();
	float first = most *RANGE_LO;
	float seconds = most *RANGE_HI;
	float sum = 0;
	int times = 0;
	for (int i = 0; i < num_freq; i++){
		if (freq_array[i] < seconds && freq_array[i] > first){
			times++;
			sum += freq_array[i];
		}
	}
	return sum / times;
}
void print(float *data, int blockSize){
	for (int i = 0; i < blockSize; i++){
		if (data[i] != 0.0)
			printf("bin = %d  %.10f  \n ", i, data[i]);
		else
			printf("bin = %d  F*****   \n", i);
	}
}

void setBlockData(uint32_t blockSize, float freq, float phaseIncr, float phaseLine, float pitch){
	//for (uint32_t s = 0; s<blockSize; s++)
	//{
	//	if (freq > 0)
	//		sinBuffer_Hel[sinIndex] = sinf(phase) /* * env[s] */; //write sine wave into audio buffer (phase will wrap)
	//	else
	//		sinBuffer_Hel[sinIndex] = sinf(phaseLine);
	//	
	//	pitchGraph_Hel[sinIndex] = pitch;
	//	sinIndex++;
	//	phase += phaseIncr; // increment the phase
	//}
}

void HightestAmplitude(float * sample, uint32_t size, float &maxnag, float &maxpos){
	
	for (uint32_t i = 0; i < size; i++){
		if (maxpos < sample[i])
			maxpos = sample[i];
		if (maxnag > sample[i])
			maxnag = sample[i];
	}
	
}
float mul = 0;
void Normalize(float * rawSample, float *outSample, float mulx, uint32_t size){
	for (uint32_t i = 0; i < size; i++){
		outSample[i] = rawSample[i] * mulx;
	}

}
void NormalizeSample(float * rawSample, float *outSample, uint32_t size){
	float maxnag = 0.0, maxpos = 0.0;
	HightestAmplitude(rawSample, size, maxnag, maxpos);
	float max = (abs(maxnag) > abs(maxpos)) ? abs(maxnag) : abs(maxpos);
	/*if (maxnag > -maxpos){
		max = maxnag;
	}
	else max = -maxpos;*/

	mul = 1 / max;
	Normalize(rawSample, outSample, mul, size);
}
void processBlock(float* samples, uint32_t blockSize, icstdsp::AudioFile *inputFile)
{
	helmholtz->iosamples(samples, hhout, blockSize);
	float freq_Hel = initialFrequency;
	float harmonic;
	//Helmoholtz
	if (helmholtz->getperiod() > 0.f){
		freq_Hel = float(inputFile->GetRate()) / helmholtz->getperiod();

		// compensate for harmonic jumping //BYPASS THIS IF NO FREQUENCY SPECIFIED
		if (initialFrequency > 0){
			harmonic = freq_Hel / initialFrequency;
			if (harmonic < 1)
				freq_Hel = freq_Hel * round(1 / harmonic);
			else
				freq_Hel = freq_Hel / round(harmonic);

			if (helmholtz->getfidelity() >= configPre->Helmholtz_Fidelity)
				hold_freq = freq_Hel;
			else
				freq_Hel = hold_freq;
		}
		else{
			hold_freq = freq_Hel;
		}
	}

	//calculate average frequency
	if (helmholtz->getfidelity() > .95){
		freq_array[num_freq] = freq_Hel;
		freq_array_rounded[num_freq_rounded] = (int)round(freq_Hel);
		num_freq_rounded++;
		num_freq++;
	}

	// calculate the phase increment for the detected frequency
	double phaseIncr_Hel = 0.0;
	double phaseLine_Hel = 0.0;
	phaseIncr_Hel = ((1.f / inputFile->GetRate()) * freq_Hel) * twopi;
	if (freq_Hel > 0){}
	else{
		phaseLine_Hel = ((1.f / inputFile->GetRate()) * hold_freq) * twopi*(blockSize - 1);
	}
	double newPitch_Hel = 0;
	if (initialFrequency > 0)
		newPitch_Hel = initialFrequency / freq_Hel - 1;
	else
		newPitch_Hel = 1.0 / freq_Hel; //NO longer need this now
	//-------------------------------------------

	////SigMund
	//sigmund->processBlock(samples, blockSize);
	//float freq_Sig = initialFrequency;
	//float hold_freq_Sig = 0;
	//if (sigmund->getFreq() > 0)
	//	freq_Sig = sigmund->getFreq();
	//else{
	//	hold_freq = freq_Sig;
	//}

	//// compensate for harmonic jumping //BYPASS THIS IF NO FREQUENCY SPECIFIED
	//if (freq_Sig > 0){
	//	harmonic = freq_Sig / initialFrequency;
	//	if (harmonic < 1)
	//		freq_Sig = freq_Sig * round(1 / harmonic);
	//	else
	//		freq_Sig = freq_Sig / round(harmonic);
	//}else{
	//	hold_freq_Sig = freq_Sig;
	//}
	//freq_array_Sig[num_freq_Sig] = freq_Sig;
	//num_freq_Sig++;

	double phaseIncr_Sig = 0.0;
	double phaseLine_Sig = 0.0;
	//phaseIncr_Sig = ((1.f / inputFile->GetRate()) * freq_Sig) * twopi;
	//if (freq_Sig > 0){}
	//else{
		phaseLine_Hel = ((1.f / inputFile->GetRate()) * hold_freq) * twopi*(blockSize - 1);
	//}
	//double newPitch_Sig = 0;
	//if (initialFrequency > 0)
		//newPitch_Sig = initialFrequency / freq_Sig - 1;
	//else
		//newPitch_Sig = 1.0 / freq_Hel; 

	//-------------------------------------------
	for (uint32_t s = 0; s<blockSize; s++)
	{
		if (freq_Hel > 0 )
			sinBuffer_Hel[sinIndex] = sinf(phase_Hel);
		else
			sinBuffer_Hel[sinIndex] = sinf(phaseLine_Hel);

		//if (freq_Sig > 0 )
		//	sinBuffer_Sig[sinIndex] = sinf(phase_Sig);
		//else
		//	sinBuffer_Sig[sinIndex] = sinf(phaseLine_Sig);

		
		pitchGraph_Hel[sinIndex] = newPitch_Hel;
//		pitchGraph_Sig[sinIndex] = newPitch_Sig;
		sinIndex++;
		phase_Hel += phaseIncr_Hel;
		//phase_Sig += phaseIncr_Sig;
	}

	// Separate Noise///
	//separator->processBlock(samples, blockSize, freq_Hel);

}
void getPeak(float * rawDataChannel, uint32_t begT, uint32_t endT, uint32_t &positionPos, uint32_t &positionNag){
	float max = -0;
	float min = 0;
	uint32_t positionPeakPos = 0;
	uint32_t positionPeakNag = 0;

	for (uint32_t i = begT; i <= endT;i++){
		if (rawDataChannel[i] > max)
		{
			max = rawDataChannel[i];
			positionPeakPos = i;
		}

		if (rawDataChannel[i] < min)
		{
			min = rawDataChannel[i];
			positionPeakNag = i;
		}
	}

	positionPos = positionPeakPos;
	positionNag = positionPeakNag;
}
void processSquare( uint32_t length , float * rawDataChannel, float* sinChannel, float *squareChannelpos = NULL, float *squareChannelnag = NULL, float *redChannel = NULL)
{
	if (sinChannel == NULL) return;
	float *peakpos = squareChannelpos;
	float *peaknag = squareChannelnag;
	float *peakred = redChannel;
	if (peakpos != NULL)
		memset(peakpos, 0, length*sizeof(float));// Init zero
	if (peaknag != NULL)
		memset(peaknag, 0, length*sizeof(float));// Init zero
	if (peakred != NULL)
		memset(peakred, 0, length*sizeof(float));// Init zero
	uint32_t begT = 0;
	uint32_t endT = -1;

	uint32_t begTred = 0;
	uint32_t endTred = 0;

	uint32_t positionPos = 0;
	uint32_t positionNag = 0;
	bool hightPos = false;
	bool hightNag = false;

	float begamplitude = 0.0;
	float endamplitude = 0.0;
	int up_flag = 0;

	for (uint32_t i = 1; i < length-1; i++)
	{
		// Nagative & Positive
		if (peaknag || peakpos){
			if (sinChannel[i] == 0 || (sinChannel[i] < 0 && sinChannel[i + 1] > 0))
			{
				begT = endT + 1;
				endT = i;
				getPeak(rawDataChannel, begT, endT, positionPos, positionNag);

				for (uint32_t j = begT; j <= endT; j++){
					if (peakpos != NULL){
						if (j == positionPos)
							hightPos = !hightPos;
						if (hightPos){
							peakpos[j] = sinf(twopi / 4);
						}
						else
						{
							peakpos[j] = sinf(twopi / 4) * -1;
						}
					}

					if (peaknag != NULL){
						if (j == positionNag)
							hightNag = !hightNag;
						if (hightNag){
							peaknag[j] = sinf(twopi / 4);
						}
						else
						{
							peaknag[j] = sinf(twopi / 4) * -1;
						}
					}
				}
			}
		}
		

		// Red wave
		if (peakred){
			if (rawDataChannel[i] > rawDataChannel[i - 1]){ //Up
				if (up_flag == -1 ){ // Down
					begTred = endTred;
					endTred = i;
					begamplitude = endamplitude;
					endamplitude = abs(rawDataChannel[i]);
					//printf("beg %f end %f \n", begamplitude, endamplitude);
					float k = (endamplitude - begamplitude) / (endTred - begTred);
					//printf("%f \n", k);
					for (int beg = begTred; beg < endTred; beg++){
						if (begTred != 0)
							peakred[beg] = begamplitude + k* (beg - begTred);
						else
							peakred[beg] = endamplitude;
					}
				}
				
				up_flag = 1;
			}
			else if (rawDataChannel[i] < rawDataChannel[i - 1]){ //dOWN
				if (up_flag == 1){ // up
					begTred = endTred;
					endTred = i;
					begamplitude = endamplitude;
					endamplitude = abs(rawDataChannel[i]);
					//printf("beg %f end %f \n", begamplitude, endamplitude);
					float k = (endamplitude - begamplitude) / (endTred - begTred);
					//printf("%f \n", k);
					for (int beg = begTred; beg < endTred; beg++){
						if (begTred != 0)
							peakred[beg] = begamplitude + k* (beg - begTred);
						else
							peakred[beg] =endamplitude;
					}
				}
				up_flag = -1;
			}
			else
			{

			}
		}
	}
	
	if (peakred){
		if (endTred < length - 1){
			begTred = endTred;
			endTred = length - 2;
			begamplitude = endamplitude;
			endamplitude = rawDataChannel[length - 2];
			//printf("beg %f end %f \n", begamplitude, endamplitude);
			//float k = (endamplitude - begamplitude) / (endTred - begTred);
			//printf("%f \n", k);
			for (int beg = begTred; beg < endTred; beg++){
				peakred[beg] = abs( begamplitude);// +k* (beg - begTred);
			}

		}
	}
}
void processResynthesize(uint32_t length, uint32_t samplerate, float intitfreq, float * rawDataChannel, float * amplitudeGraphChannel, float *resynthesizeChannel)
{
	float * aplitudeChannel = NULL;
	
	if (resynthesizeChannel){
		if (amplitudeGraphChannel)
			aplitudeChannel = amplitudeGraphChannel;
		else{
			aplitudeChannel = new float[length];
			processSquare(length, rawDataChannel, NULL, NULL, NULL, aplitudeChannel);
		}
		float incPhase = ((1.f / samplerate) * intitfreq) * twopi;
		for (uint32_t i = 0; i < length - 1; i++){
			resynthesizeChannel[i] = aplitudeChannel[i] * sinf(incPhase * i);
		}
	}
}
/*void separateNoise(uint32_t length, uint32_t sampleRate, float * rawDataChannel, float *noiseChannel, float * harmonicChannel){
	const int FFTSize = 32768;
	separator = new Separator(FFTSize, OVERLAP, sampleRate, 20000, 4);
	separator->processBlock(rawDataChannel + blockStart, numSamplesInBlock,)
	for (uint32_t blockStart = 0; blockStart < length; blockStart += FFTSize)
	{
		uint32_t numSamplesInBlock = FFTSize;

		if (blockStart + FFTSize > length)
			numSamplesInBlock = length % FFTSize;
		if (blockStart + blockSize > length)
			numSamplesInBlock = length % FFTSize;

		if (numSamplesInBlock)
		{
			separator->processBlock(rawDataChannel + blockStart, numSamplesInBlock,)
		}
	}


}
*/
float processFile(const char *path, int frameSize, float initFrequency, int analChannel){
	analysisChannel = analChannel;
	initialFrequency = initFrequency;
	icstdsp::AudioFile outputFile;

	phase_Hel = 0.; // phase of the sine wave. will be incremented on each sample
	phase_Sig = 0.; // phase of the sine wave. will be incremented on each sample
	sinIndex = 0; // index to write sine wav
	hold_freq = initialFrequency;
	num_freq_Sig = 0;
	sum = 0;
	times = 0;
	avg_frequency_hel = 0;
	avg_frequency_sig = 0;

	num_freq = 0;
	num_freq_rounded = 0;
	printf(" %5d  ", fileIndex);
	icstdsp::AudioFile *inputFile = new icstdsp::AudioFile();;
	if (inputFile->Load(const_cast<char *>(path), 0, 0, false)) {
		printf("Couldn't load inputFile\n");
		return -1;
	}

	if (analysisChannel + 1 > inputFile->GetChannels()) {
		printf("analysis channel out of range\n");
		return -1;
	}

	printf("Frame Size %i, Initial Freq %f, Analysis Channel %i\n", frameSize, initialFrequency, analysisChannel+1);

	// allocate new helmoltz object dynamically, since we need to adjust the frameSize
	helmholtz = new Helmholtz(frameSize, OVERLAP);
	//sigmund = new sigmundcpp(configPre->Sigmund_Npts,configPre->Sigmund_HopSize);

	//sigmund->set_sr(inputFile->GetRate());
	uint32_t fileFrames = inputFile->GetSize();
	int numchannel = 0;
	sinBuffer_Hel = new float[fileFrames];
	//sinBuffer_Sig = new float[fileFrames];
	pitchGraph_Hel = new float[fileFrames];
	//pitchGraph_Sig = new float[fileFrames];
	freq_array = new float[fileFrames / blockSize + blockSize];
	//freq_array_Sig = new float[fileFrames / blockSize + blockSize];//(float*)malloc((fileFrames / blockSize + 2* blockSize)*sizeof(float));
	freq_array_rounded = new int[fileFrames / blockSize + blockSize];

	

	// Normalization
	float * rawChannelInput = NULL;
	if (configPre->Normalize_for_Detection){
		//rawChannelInput = new float[fileFrames];
		rawChannelInput = inputFile->GetSafePt(analysisChannel, true);
		NormalizeSample(inputFile->GetSafePt(analysisChannel, true), rawChannelInput, fileFrames);
	}
	else{
		rawChannelInput = inputFile->GetSafePt(analysisChannel, true);
	}

	//separator
	//separator = new Separator(16384, 4000, inputFile->GetRate(), initFrequency, configPre->Helmholtz_Fidelity, 5000, 100, configPre->Window_Type);
	
	int ll = 1;
	// loop through input file in chunks of blockSize
	for (uint32_t blockStart = 0; blockStart < fileFrames; blockStart += blockSize)
	{
		uint32_t numSamplesInBlock = blockSize;

		if (blockStart + blockSize > fileFrames)
			numSamplesInBlock = fileFrames % blockSize;

		if (numSamplesInBlock)
		{
			processBlock(/*inputFile->GetSafePt(analysisChannel, true)*/rawChannelInput + blockStart, numSamplesInBlock, inputFile);
			
			ll++;
		}

	}


	if (configPre->Normalize_for_Detection){
		rawChannelInput = inputFile->GetSafePt(analysisChannel, true);
		Normalize(rawChannelInput, rawChannelInput, 1.0 / mul, fileFrames);
	}
	//
	//separator->processData(fileFrames, rawChannelInput, noiseDataChannel, harmonicDataChannel);


	// Get Avg frequency
	avg_frequency_hel = new_avg();

	int new_chan = 0;

	if (configPre->MaxFreq_Separate > 0){
		int each_raw_channel = 0;
		if (configPre->Original){
			each_raw_channel++;
		}

		if (configPre->Noise_Channel){
			each_raw_channel++;
		}

		if (configPre->Harmonics){
			each_raw_channel++;
		}

		if (configPre->Combined){
			each_raw_channel++;
		}

		if (configPre->Fundamental && !configPre->Individual_Harmonics) {
			each_raw_channel++;
		}

		if (configPre->Recreate_Harmonics){
			each_raw_channel += (int)(configPre->MaxFreq_Separate / initFrequency);
		}

		if (configPre->Individual_Harmonics){
			each_raw_channel += (int)(configPre->MaxFreq_Separate / initFrequency);
		}
		new_chan = each_raw_channel * inputFile->GetChannels();

	}

	/*if (configPre->Original)
	{
		new_chan += inputFile->GetChannels() + configPre->getNumberChannelAdded();
	}
	else{
		new_chan += configPre->getNumberChannelAdded();
	}*/
		//
	// allocate memory for output file (+ 1 channel)

	if (0 != outputFile.Create(fileFrames, inputFile->GetChannels() + configPre->getNumberChannelAdded() + new_chan, inputFile->GetResolution(), inputFile->GetRate())){
		printf("%s SKIPPPPPPPPPPPPP******\n", path); return 0;
	}
	float *testChannel = NULL;
	if (configPre->TestChannel)
		testChannel = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberTestChannel(), true);

	float *amplitudeGraphChannel = NULL;
	if (configPre->AmplitudeGraph)
		amplitudeGraphChannel = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelAmplitudeGraph(), true);

	float *resynthesisChannel = NULL;
	if (configPre->Resynthesize)
		resynthesisChannel = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelResynthesize(), true);

	float *sinDataChannel_Hel = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelSinChanHel(), true);
	//float *sinDataChannel_Sig = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelSinChanSig(), true);
	float *pitchDataChannel_Hel = NULL;
	if (configPre->pitchGraph_Hel)
		pitchDataChannel_Hel = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelPitchChanHel(), true);
	//float *pitchDataChannel_Sig = NULL;
	//if (configPre->pitchGraph_Sig)
		//pitchDataChannel_Sig = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelPitchChanSig(), true);
	float *squareDataChannelPos = NULL;
	if (configPre->isAddPositive())
		squareDataChannelPos = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelPos(), true);
	float *squareDataChannelNag = NULL; 
	if (configPre->isAddNegative())
		squareDataChannelNag = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelNag(), true);

	/*float *noiseDataChannel = NULL;
	if (configPre->Channel_Noise)
		noiseDataChannel = outputFile.GetSafePt(inputFile->GetChannels() + configPre->getNumberChannelNoise(), true);*/

	//0 raw data channel
	//1 sin channel
	//2 Pitch
	//3 square channel
			
	float *rawDataChannel = inputFile->GetSafePt(analysisChannel, true);
	
	/*if (initFrequency != 0){
		avg_frequency_hel /= initFrequency;
	}else{}*/
	//avg_frequency_sig = avg_frequency_hel;// not implement yet
	
	//uint32_t delay_compensation = configPre->Sigmund_Npts;
	//uint32_t new_size_frame = fileFrames - configPre->Sigmund_Npts - (frameSize / OVERLAP) - 1;;
	// write input file to output file channels, and stick sine wave on as extra channel
	for (uint32_t s = 0; s < fileFrames; s++)
	{
		for (uint32_t chan = 0; chan < inputFile->GetChannels(); chan++)
		{
			float * rawdata = inputFile->GetSafePt(chan, true);
			float *outputdata = outputFile.GetSafePt(chan, true);
			outputdata[s] = rawdata[s];
		}
		//write sine wave to last channel
		uint32_t offsetSampleIdx = s + (frameSize / OVERLAP);
		if (offsetSampleIdx < fileFrames){
			if (configPre->Helmholtz_Sinewave)
				sinDataChannel_Hel[s] = sinBuffer_Hel[offsetSampleIdx];

			//if (configPre->Sigmund_Sinewave){
			//	sinDataChannel_Sig[s] = 0.005;
			//	 
			//	if (configPre->DelayCompensation_Sig){
			//		if (s > new_size_frame) {
			//			sinDataChannel_Sig[s] = 0.00;
			//		}
			//		else
			//		{
			//			sinDataChannel_Sig[s] = sinBuffer_Sig[offsetSampleIdx + delay_compensation];
			//			printf("index %d , data = %f , index de - %d , data de %f\n ", s, sinDataChannel_Sig[s], offsetSampleIdx + delay_compensation, sinBuffer_Sig[offsetSampleIdx + delay_compensation]);
			//		}

			//	}
			//	else{
			//		sinDataChannel_Sig[s] = sinBuffer_Sig[offsetSampleIdx];
			//	}
			//	
			//	
			//}
				

			if (configPre->pitchGraph_Hel){
				if (initialFrequency > 0){
					pitchDataChannel_Hel[s] = pitchGraph_Hel[offsetSampleIdx];
				}
				else
					pitchDataChannel_Hel[s] = pitchGraph_Hel[offsetSampleIdx] * avg_frequency_hel - 1;
				
			}

			//if (configPre->pitchGraph_Sig){
			//	float value = 0.0;
			//	if (configPre->DelayCompensation_Sig){
			//		if (s > new_size_frame) {
			//			value = 0.0;
			//		}
			//		else{
			//			value = pitchGraph_Sig[offsetSampleIdx + delay_compensation];
			//		}
			//	}
			//	else{
			//		value = pitchGraph_Sig[offsetSampleIdx];
			//	}
			//	
			//	if (initialFrequency > 0){
			//		pitchDataChannel_Sig[s] = value;// pitchGraph_Sig[offsetSampleIdx + delay];
			//	}
			//	else{
			//		pitchDataChannel_Sig[s] = value /*pitchGraph_Sig[offsetSampleIdx + delay]*/ *avg_frequency_sig - 1;
			//	}	
			//}
		}
	}
	// Process Square Channel
	processSquare(fileFrames, rawDataChannel, sinDataChannel_Hel, squareDataChannelPos, squareDataChannelNag, amplitudeGraphChannel); // Both Nagtive and Positive 
	processResynthesize(fileFrames, outputFile.GetRate(), avg_frequency_hel, sinDataChannel_Hel, amplitudeGraphChannel, resynthesisChannel);
	
	
	
	
	if (configPre->MaxFreq_Separate > 0){

		int startChannel = inputFile->GetChannels() + configPre->getNumberChannelAdded();

		int curr_channel = startChannel;

		

		for (int chan = 0; chan < inputFile->GetChannels(); chan++){

			float *dataChanProcess = inputFile->GetSafePt(chan, true);


			
			Harmonic * harmonic = new Harmonic(dataChanProcess, fileFrames, configPre->Overlap_Separate, configPre->BlockSize_Separate, inputFile->GetRate(), 10, initFrequency, configPre->MaxFreq_Separate, /*initFrequency*/configPre->BandFrequency_Separate, configPre->Window_Type);


			

			if (configPre->Original){
				float *tmp3 = outputFile.GetSafePt(curr_channel);
				memcpy(tmp3, dataChanProcess, fileFrames * sizeof(float));
				curr_channel++;
			}

			if (configPre->Noise_Channel){
				float *tmp4 = outputFile.GetSafePt(curr_channel);
				printf("Create Noise Channel \n");
				harmonic->processNoise();
				memcpy(tmp4, harmonic->getNoiseChannel(), fileFrames * sizeof(float));
				/*if (configPre->Normalize_for_Detection)
					Normalize(tmp4, tmp4,1.0/mul,fileFrames);*/
				curr_channel++;
			}
			if (configPre->Harmonics || configPre->Combined || configPre->Fundamental || configPre->Individual_Harmonics)
				harmonic->processChannel();
			if (configPre->Harmonics){
				float *tmp6 = outputFile.GetSafePt(curr_channel);
				memcpy(tmp6, harmonic->getcombinedChannel(), fileFrames * sizeof(float));
				/*if (configPre->Normalize_for_Detection)
					Normalize(tmp6, tmp6, 1.0 / mul, fileFrames);*/
				curr_channel++;
			}

			if (configPre->Combined){
				float *tmp5 = outputFile.GetSafePt(curr_channel);
				memcpy(tmp5, harmonic->getoutputChannel(), fileFrames * sizeof(float));
				/*if (configPre->Normalize_for_Detection)
					Normalize(tmp5, tmp5, 1.0 / mul, fileFrames);*/
				curr_channel++;
			}

			if (configPre->Fundamental && !configPre->Individual_Harmonics){
				float *tmp7 = outputFile.GetSafePt(curr_channel);
				memcpy(tmp7, harmonic->getHarmonicChannels(0 + 1), fileFrames * sizeof(float));
				/*if (configPre->Normalize_for_Detection)
					Normalize(tmp7, tmp7, 1.0 / mul, fileFrames);*/
				curr_channel++;
			}

			for (int i = 0; i < harmonic->getHarmonicNumber() && configPre->Individual_Harmonics; i++){

				if (configPre->Individual_Harmonics){
					float *tmp1 = outputFile.GetSafePt(curr_channel);
					memcpy(tmp1, harmonic->getHarmonicChannels(i + 1), fileFrames * sizeof(float));
					/*if (configPre->Normalize_for_Detection)
						Normalize(tmp1, tmp1, 1.0 / mul, fileFrames);*/
					curr_channel++;
				}
			}
				
			for (int i = 0; i < harmonic->getHarmonicNumber() && configPre->Recreate_Harmonics; i++){
				// Amplitude Channel
				/*float *tmp2 = outputFile.GetSafePt(startChannel + i * 3 + 1);
				harmonic->createAmplitudeHarmonic(tmp1, tmp2);
				memcpy(tmp2, harmonic->getAmplitudeChannel(i + 1), fileFrames * sizeof(float));*/
				if (configPre->Recreate_Harmonics){
					float *tmp3 = outputFile.GetSafePt(/*startChannel + i/*3 + 2*/ curr_channel);
					memcpy(tmp3, harmonic->getHamonicChannelCreated(i + 1), fileFrames * sizeof(float));
					//Normalize(tmp3, tmp3, 1.0 / mul, fileFrames);
					curr_channel++;
				}
			}
			delete harmonic;
		}		
	}
	

	std::string name = "";
	try{
		name = string(path);
	}
	catch (...){}
	
	std::regex match("(.+\\\\)?(.+)(\\.[\\w\\d]+)");

	std::string path = std::regex_replace(name, match, "$1");
	std::string file = std::regex_replace(name, match, "$2");
	std::string ext = std::regex_replace(name, match, "$3");
	
	name = "";
	if (configPre->RenameFiles_Prefix[0] != 0)
		name += string(configPre->RenameFiles_Prefix);
	name += file;
	if (configPre->RenameFiles_AverageFrequency){
		char pre[200] = { 0 };
		sprintf(pre, "`f=%3.9f", avg_frequency_hel);
		name += string(pre);
	}
	
	name += ext;
	if (configPre->isValidateOutputFolder()){
		name = string(configPre->OutputFolder)+"\\" + name;
	}else
		name = path + name;
	outputFile.SaveWave(const_cast <char *> (name.c_str()));
	outputFile.~AudioFile();
	delete inputFile;
	inputFile = NULL;
	delete helmholtz;
	helmholtz = NULL;
	//delete separator;
	//separator = NULL;
//	sigmund->clear();
//	delete sigmund;
//	sigmund = NULL;

	delete[] sinBuffer_Hel;
	sinBuffer_Hel = NULL;

	delete[] sinBuffer_Sig;
	sinBuffer_Sig = NULL;

	if (pitchGraph_Hel){
		delete[] pitchGraph_Hel;
			pitchGraph_Hel = NULL;
	}
	if (pitchGraph_Sig){
		delete[] pitchGraph_Sig;
		pitchGraph_Sig = NULL;
	}
	if (freq_array_Sig){
		delete[] freq_array_Sig;
		freq_array_Sig = NULL;
	}
	
	// Cap phat freq_array_rounded
	if (freq_array){
		delete[] freq_array;
		freq_array = NULL;
	}
	if (freq_array_rounded){
		delete[] freq_array_rounded; 
		freq_array_rounded = NULL;
	}
	return avg_frequency_hel;	
}
char** loadfile(char *path, int &lines){
	FILE* file = NULL;
	int files = 0;
	char tmpName[MaxNameFile] = { 0 };
	file = fopen(path, "r");
	while (fgets(tmpName, MaxNameFile, file) != NULL)  files++;
	rewind(file);
	char ** listname = (char**)malloc(sizeof(char*)*files/*Not good but i will improve later*/);
	memset(listname, 0, files * sizeof(char*)); // init to null list pointer
	lines = 0;
	if (file != NULL){
		while (fgets(tmpName, MaxNameFile, file) != NULL){
			listname[lines] = (char *)malloc(strlen(tmpName) + 1);// Malloc memmory
			strcpy(listname[lines], tmpName); // copy to list
			lines++;
		}
	}
	else{
		printf("Open file: %s error, file does not exist \n", path);
		return NULL;
	}

	if (file != NULL)
		fclose(file);
	return listname;
}
bool isNumber(char c){
	return ((c <= '9') && (c >= '0'));
}
double mtof(const char *midinote){//midi to frequency
	int i = 0;

	for (; i < 256; i++){
		if (strcmp(midichart[i], midinote) == 0){
			break;
		}
	}
	if (i > 127){ i -= 128; }

	if (i >= 0 && i < 127){
		return freqchart[i];
	}

	return -1;
}


double mtofoffset(const char * midinote, int offset){
	int i = 0;

	for (; i < 256; i++){
		if (strcmp(midichart[i], midinote) == 0){
			break;
		}
	}
	if (i > 127){ i -= 128; }

	if (i >= 0 && i < 127){
		return freqchart[i + offset];
	}
	return -1;
}
void writelof(char* path, Preferences *config, char * name){
	int lines = 0;
	blockSize = config->blockSize;
	hhout = new float[blockSize];
	char ** listname = loadfile(path, lines);
	std::regex matchFile("\"?(.+\\\\)?(.+)(\\.[\\w\\d]+).*\"?\\n?");
	std::regex matchMidi("n=((?:\\d{1,3})|(?:[A-Za-z]#?\\-?\\d))");
	std::regex matchmidiOffset("o=(-?\\d+)");
	std::regex matchCh("ch=(\\d+)");
	std::regex matchFS("fs=(\\d+)");
	std::regex matchWarp("w=(\\d+)");
	std::string pathname = std::regex_replace(string(path), matchFile, "$1");
	pathname += string(name);
	configPre = config;
	FILE *file = NULL;
	file = fopen(pathname.c_str(), "w");
	if (file != NULL){
		for (int i = 0; i < lines; i++){
			fileIndex = i +1;
			char tmp[2000] = { 0 };
			try {
				std::string fullpathname = std::regex_replace(string(listname[i]), matchFile, "$1$2$3");
				std::string filename = std::regex_replace(string(listname[i]), matchFile, "$2");
				std::string midinoteArg = std::regex_replace(string(listname[i]), matchMidi, "$1", std::regex_constants::format_no_copy);
				std::string midiOffsetArg = std::regex_replace(string(listname[i]), matchmidiOffset, "$1", std::regex_constants::format_no_copy);
				std::string channelArg = std::regex_replace(string(listname[i]), matchCh, "$1", std::regex_constants::format_no_copy);
				std::string framesizeArg = std::regex_replace(string(listname[i]), matchFS, "$1", std::regex_constants::format_no_copy);
				std::string warpArg = std::regex_replace(string(listname[i]), matchWarp, "$1", std::regex_constants::format_no_copy); //change here

				channel = config->Channel;
				if (channelArg != "") channel = atoi(channelArg.c_str()) -1;
				
							

				// Get initial frequency
				float initFreq = 0.0;
				if (midinoteArg.length()>0) {
					initFreq = mtof(midinoteArg.c_str());
					if (midiOffsetArg.length() > 0){
						initFreq = mtofoffset(midinoteArg.c_str(), atoi(midiOffsetArg.c_str()));
					}
				}
				if (warpArg.length() > 0) {
					initFreq = atoi(warpArg.c_str());
				}

				// Get framesize for pitch detection
				int framesize = 4096;
				if (framesizeArg != "") framesize = atoi(framesizeArg.c_str());
				else {
					if (initFreq >= 50) framesize = 4096;
					if (initFreq >= 100) framesize = 2048;
					if (initFreq >= 200) framesize = 1024;
					if (initFreq >= 400) framesize = 512;
					if (initFreq >= 800) framesize = 256;
				}

				sprintf(tmp, "%5d %s`f=%3.10f\n", fileIndex, filename.c_str(), processFile(fullpathname.c_str(), framesize, initFreq, channel));
				fputs(tmp, file);
			}
			catch (exception &a){
				sprintf(tmp, "%s SKIPED  ***************  \n", listname[i]);
				fputs(tmp, file);
			}
		}
	}
	delete configPre;
	if (file != NULL)
		fclose(file);
}


float RandDomPhaseList[] = {
	0.8735,
	0.8135,
	0.1122,
	0.804,
	0.374,
	0.9405,
	0.4443,
	0.1048,
	0.065,
	0.2262,
	0.8547,
	0.3324,
	0.0135,
	0.6299,
	0.9659,
	0.5148,
	0.2167,
	0.4117,
	0.5123,
	0.1192,
	0.9914,
	0.9139,
	0.9188,
	0.9284,
	0.8382,
	0.2882,
	0.5159,
	0.706,
	0.5387,
	0.7908,
	0.4607,
	0.6429,
	0.2647,
	0.308,
	0.7565,
	0.4311,
	0.2987,
	0.4698,
	0.708,
	0.3847,
	0.2597,
	0.2804,
	0.3812,
	0.9874,
	0.1189,
	0.602,
	0.1069,
	0.8856,
	0.7224,
	0.7769,
	0.6267,
	0.5687,
	0.7458,
	0.5478,
	0.3131,
	0.5843,
	0.6163,
	0.0349,
	0.7198,
	0.7498,
	0.9762,
	0.4209,
	0.9849,
	0.0371,
	0.7008,
	0.1483,
	0.5822,
	0.5248,
	0.3836,
	0.9922,
	0.8278,
	0.9194,
	0.9084,
	0.3092,
	0.5394,
	0.3748,
	0.3742,
	0.6536,
	0.2413,
	0.5264,
	0.603,
	0.8655,
	0.7717,
	0.1332,
	0.2663,
	0.6341,
	0.5785,
	0.2165,
	0.8167,
	0.9743,
	0.8022,
	0.0097,
	0.6352,
	0.0667,
	0.3727,
	0.5699,
	0.3375,
	0.1163,
	0.4338,
	0.2979,
	0.9278,
	0.8945,
	0.1312,
	0.8521,
	0.6509,
	0.6669,
	0.2613,
	0.4091,
	0.6589,
	0.0738,
	0.9327,
	0.0745,
	0.5598,
	0.6414,
	0.1731,
	0.6684,
	0.8716,
	0.6167,
	0.7303,
	0.3442,
	0.3347,
	0.4313,
	0.5276,
	0.7532,
	0.4825,
	0.0357,
	0.3798,
	0.7496,
	0.7616,
	0.8842,
	0.3041,
	0.6477,
	0.4451,
	0.6094,
	0.6568,
	0.6405,
	0.5428,
	0.7784,
	0.1298,
	0.0037,
	0.6031,
	0.8928,
	0.8555,
	0.7711,
	0.996,
	0.7425,
	0.5894,
	0.0924,
	0.6432,
	0.7935,
	0.5573,
	0.9388,
	0.0251,
	0.6065,
	0.4672,
	0.7383,
	0.4806,
	0.779,
	0.5793,
	0.3137,
	0.7797,
	0.6849,
	0.5914,
	0.1111,
	0.3931,
	0.866,
	0.3974,
	0.2553,
	0.7999,
	0.5635,
	0.8904,
	0.7849,
	0.1602,
	0.4481,
	0.0401,
	0.8149,
	0.1295,
	0.4505,
	0.5388,
	0.4147,
	0.5083,
	0.2729,
	0.0167,
	0.4601,
	0.4963,
	0.7453,
	0.3536,
	0.8308,
	0.4645,
	0.2541,
	0.6245,
	0.93,
	0.9217,
	0.2888,
	0.7676,
	0.63,
	0.2233,
	0.552,
	0.2693,
	0.1708,
	0.9085,
	0.5713,
	0.6368,
	0.7345,
	0.433,
	0.8811,
	0.4471,
	0.1676,
	0.5642,
	0.0608,
	0.3268,
	0.5625,
	0.6388,
	0.9323,
	0.0358,
	0.7567,
	0.0623,
	0.6479,
	0.5985,
	0.2143,
	0.004,
	0.5959,
	0.82,
	0.7381,
	0.7546,
	0.6488,
	0.7481,
	0.7196,
	0.2168,
	0.5999,
	0.9211,
	0.949,
	0.7075,
	0.8731,
	0.6008,
	0.6716,
	0.7793,
	0.4775,
	0.8016,
	0.6779,
	0.428,
	0.8045,
	0.9153,
	0.1811,
	0.5068,
	0.3457,
	0.7284,
	0.8893,
	0.6835,
	0.6801,
	0.0498,
	0.2653,
	0.1176,
	0.2648,
	0.7364,
	0.3592,
	0.6472,
	0.191,
	0.8316,
	0.1603,
	0.0587,
	0.8287,
	0.3155,
	0.0629,
	0.8142,
	0.2997,
	0.8068,
	0.5513,
	0.1775,
	0.1823,
	0.5035,
	0.4379,
	0.3708,
	0.2944,
	0.3988,
	0.2898,
	0.0085,
	0.7615,
	0.3699,
	0.2684,
	0.8207,
	0.3951,
	0.5051,
	0.8467,
	0.6968,
	0.1373,
	0.3352,
	0.4513,
	0.0568,
	0.1376,
	0.39,
	0.6808,
	0.7258,
	0.3712,
	0.3232,
	0.3395,
	0.1303,
	0.4036,
	0.0009,
	0.915,
	0.8857,
	0.0694,
	0.5865,
	0.2582,
	0.7583,
	0.9848,
	0.4386,
	0.1956,
	0.0289,
	0.4017,
	0.1992,
	0.968,
	0.216,
	0.2052,
	0.323,
	0.9951,
	0.8218,
	0.2338,
	0.1357,
	0.1858,
	0.6187,
	0.3348,
	0.2393,
	0.3471,
	0.3336,
	0.2795,
	0.6614,
	0.0773,
	0.7535,
	0.9632,
	0.4592,
	0.9868,
	0.8148,
	0.5659,
	0.8419,
	0.1655,
	0.6489,
	0.7159,
	0.7067,
	0.987,
	0.7246,
	0.502,
	0.7613,
	0.9373,
	0.8374,
	0.993,
	0.171,
	0.3946,
	0.2993,
	0.6616,
	0.9127,
	0.839,
	0.9097,
	0.0312,
	0.8018,
	0.0774,
	0.1207,
	0.9785,
	0.9912,
	0.3992,
	0.951,
	0.4884,
	0.3523,
	0.5392,
	0.6809,
	0.9999,
	0.0809,
	0.7642,
	0.0241,
	0.6915,
	0.1988,
	0.1084,
	0.4766,
	0.1424,
	0.9062,
	0.5611,
	0.551,
	0.4904,
	0.6067,
	0.8991,
	0.81,
	0.0972,
	0.7129,
	0.9631,
	0.2534,
	0.5738,
	0.2247,
	0.0101,
	0.3637,
	0.6654,
	0.0285,
	0.3365,
	0.2368,
	0.9607,
	0.3387,
	0.9574,
	0.0354,
	0.8137,
	0.3184,
	0.8665,
	0.4404,
	0.2378,
	0.7251,
	0.6484,
	0.1064,
	0.4996,
	0.4546,
	0.1065,
	0.7092,
	0.6129,
	0.9886,
	0.4899,
	0.4192,
	0.1808,
	0.2227,
	0.4186,
	0.7404,
	0.3488,
	0.3321,
	0.2883,
	0.0891,
	0.5773,
	0.5734,
	0.8336,
	0.6546,
	0.6297,
	0.114,
	0.1167,
	0.4817,
	0.4992,
	0.1168,
	0.9654,
	0.2272,
	0.5194,
	0.8847,
	0.5835,
	0.5475,
	0.7457,
	0.0862,
	0.3782,
	0.9958,
	0.1745,
	0.4836,
	0.4723,
	0.7669,
	0.1844,
	0.7622,
	0.0955,
	0.9896,
	0.062,
	0.392,
	0.6367,
	0.3694,
	0.7648,
	0.2676,
	0.5976,
	0.4653,
	0.1882,
	0.0741,
	0.7227,
	0.8718,
	0.2972,
	0.7181,
	0.6967,
	0.4539,
	0.8273,
	0.3327,
	0.5588,
	0.9681,
	0.3104,
	0.165,
	0.038,
	0.2533,
	0.305,
	0.8561,
	0.7108,
	0.8757,
	0.5788,
	0.1522,
	0.0429,
	0.4548,
	0.9622,
	0.5397,
	0.0909,
	0.903,
	0.9354,
	0.8039,
	0.0177,
	0.7656,
	0.6608,
	0.1435,
	0.7696,
	0.3525,
	0.214,
	0.3042,
	0.9522,
	0.7436,
	0.6121,
	0.0344,
	0.6073,
	0.8314,
	0.1832,
	0.9269,
	0.4219,
	0.5784,
	0.41,
	0.6213,
	0.106,
	0.982,
	0.6962,
	0.8612,
	0.5522,
	0.5293,
	0.5141,
	0.1835,
	0.246,
	0.168,
	0.4758,
	0.055,
	0.7655,
	0.6891,
	0.8737,
	0.4155,
	0.1855,
	0.7571,
	0.689,
	0.1217,
	0.6442,
	0.4099,
	0.6731,
	0.474,
	0.5195,
	0.8175,
	0.8888,
	0.2206,
	0.2502,
	0.5002,
	0.6951,
	0.5816,
	0.424,
	0.1577,
	0.5101,
	0.6712,
	0.5685,
	0.0265,
	0.8401,
	0.0287,
	0.514,
	0.2123,
	0.2487,
	0.1212,
	0.4223,
	0.0417,
	0.1308,
	0.8208,
	0.9272,
	0.4216,
	0.8375,
	0.9909,
	0.6392,
	0.2787,
	0.6698,
	0.9396,
	0.1856,
	0.6687,
	0.8369,
	0.2825,
	0.1567,
	0.7329,
	0.2277,
	0.8127,
	0.5407,
	0.2712,
	0.4087,
	0.471,
	0.672,
	0.4263,
	0.7402,
	0.9057,
	0.1774,
	0.1785,
	0.6057,
	0.3565,
	0.1261,
	0.1716,
	0.2186,
	0.4529,
	0.6735,
	0.8232,
	0.8704,
	0.3476,
	0.9216,
	0.6253,
	0.2909,
	0.3065,
	0.9699,
	0.8335,
	0.4932,
	0.9855,
	0.342,
	0.723,
	0.5647,
	0.8259,
	0.9497,
	0.3528,
	0.5434,
	0.9213,
	0.9759,
	0.8449,
	0.2196,
	0.2586,
	0.3143,
	0.0494,
	0.2481,
	0.7497,
	0.3629,
	0.1677,
	0.7511,
	0.1494,
	0.016,
	0.7359,
	0.7748,
	0.303,
	0.5231,
	0.3353,
	0.1801,
	0.6762,
	0.4569,
	0.1444,
	0.35,
	0.042,
	0.199,
	0.6625,
	0.021,
	0.4358,
	0.4151,
	0.31,
	0.5188,
	0.3415,
	0.2743,
	0.8649,
	0.6812,
	0.9862,
	0.9589,
	0.2161,
	0.9088,
	0.4211,
	0.5488,
	0.8132,
	0.3814,
	0.2907,
	0.6097,
	0.9725,
	0.2444,
	0.3543,
	0.0723,
	0.1072,
	0.5901,
	0.2811,
	0.4448,
	0.7274,
	0.2298,
	0.1749,
	0.277,
	0.7815,
	0.0486,
	0.1644,
	0.9745,
	0.5566,
	0.3953,
	0.3489,
	0.9495,
	0.8878,
	0.8854,
	0.0262,
	0.8567,
	0.6749,
	0.6091,
	0.7778,
	0.8742,
	0.973,
	0.6529,
	0.819,
	0.5435,
	0.274,
	0.8755,
	0.0138,
	0.1977,
	0.4064,
	0.2616,
	0.664,
	0.5672,
	0.6908,
	0.3977,
	0.6547,
	0.7171,
	0.0395,
	0.5574,
	0.292,
	0.5317,
	0.0978,
	0.9369,
	0.8517,
	0.8226,
	0.9694,
	0.564,
	0.8977,
	0.7771,
	0.4113,
	0.0163,
	0.0691,
	0.1737,
	0.4837,
	0.8426,
	0.4927,
	0.9101,
	0.7901,
	0.3884,
	0.2969,
	0.2539,
	0.6572,
	0.6313,
	0.1194,
	0.2187,
	0.3006,
	0.3015,
	0.6147,
	0.6444,
	0.7003,
	0.4598,
	0.4266,
	0.5182,
	0.6837,
	0.2305,
	0.9176,
	0.5058,
	0.4412,
	0.8489,
	0.3397,
	0.7666,
	0.0796,
	0.5911,
	0.6722,
	0.4514,
	0.9245,
	0.2119,
	0.4872,
	0.4375,
	0.9442,
	0.5824,
	0.0071,
	0.7105,
	0.6738,
	0.842,
	0.5447,
	0.2692,
	0.1558,
	0.487,
	0.0144,
	0.5723,
	0.1796,
	0.8448,
	0.388,
	0.8792,
	0.5333,
	0.0316,
	0.1345,
	0.6461,
	0.6919,
	0.1032,
	0.429,
	0.0552,
	0.7411,
	0.5401,
	0.6134,
	0.4339,
	0.5255,
	0.1943,
	0.7372,
	0.8891,
	0.3081,
	0.2211,
	0.9086,
	0.8942,
	0.8681,
	0.5618,
	0.2581,
	0.2856,
	0.7563,
	0.961,
	0.1672,
	0.8184,
	0.8637,
	0.7197,
	0.0611,
	0.1182,
	0.6713,
	0.2081,
	0.1172,
	0.3723,
	0.7346,
	0.5757,
	0.0554,
	0.3058,
	0.5303,
	0.8788,
	0.3119,
	0.9,
	0.6288,
	0.9032,
	0.6412,
	0.8206,
	0.9465,
	0.5902,
	0.2339,
	0.8543,
	0.8258,
	0.7965,
	0.5076,
	0.3734,
	0.4635,
	0.0605,
	0.9991,
	0.4873,
	0.3062,
	0.4962,
	0.2492,
	0.9404,
	0.5753,
	0.6258,
	0.7858,
	0.1047,
	0.9765,
	0.9122,
	0.3234,
	0.3615,
	0.6802,
	0.7056,
	0.1787,
	0.7068,
	0.5665,
	0.2365,
	0.0521,
	0.7447,
	0.1872,
	0.5437,
	0.7973,
	0.2471,
	0.8754,
	0.3294,
	0.4936,
	0.2821,
	0.2717,
	0.8429,
	0.0341,
	0.2386,
	0.381,
	0.2472,
	0.201,
	0.2401,
	0.5669,
	0.7169,
	0.5567,
	0.1411,
	0.3243,
	0.1889,
	0.1124,
	0.2353,
	0.7931,
	0.8165,
	0.3124,
	0.0899,
	0.8163,
	0.4328,
	0.5729,
	0.1583,
	0.4398,
	0.6389,
	0.4779,
	0.0952,
	0.7929,
	0.5418,
	0.4288,
	0.8574,
	0.626,
	0.069,
	0.066,
	0.9048,
	0.9158,
	0.6485,
	0.5328,
	0.8491,
	0.9262,
	0.6896,
	0.4651,
	0.2948,
	0.0882,
	0.5746,
	0.2256,
	0.5373,
	0.2988,
	0.6788,
	0.7145,
	0.1273,
	0.2765,
	0.4242,
	0.4396,
	0.5131,
	0.2453,
	0.1883,
	0.5983,
	0.0526,
	0.6154,
	0.2376,
	0.3238,
	0.2359,
	0.9618,
	0.064,
	0.0861,
	0.8433,
	0.4243,
	0.4819,
	0.6145,
	0.0206,
	0.402,
	0.5597,
	0.1527,
	0.669,
	0.9578,
	0.897,
	0.4678,
	0.2349,
	0.7903,
	0.7244,
	0.6372,
	0.8541,
	0.9561,
	0.7861,
	0.0202,
	0.1375,
	0.4886,
	0.0789,
	0.5774,
	0.6133,
	0.9192,
	0.4824,
	0.1588,
	0.8703,
	0.1059,
	0.4276,
	0.2084,
	0.5728,
	0.6202,
	0.0218,
	0.9984,
	0.972,
	0.0161,
	0.3769,
	0.2155,
	0.6597,
	0.3606,
	0.3297,
	0.87,
	0.5536,
	0.013,
	0.6856,
	0.5223,
	0.3858,
	0.2281,
	0.5675,
	0.5142,
	0.3797,
	0.1131,
	0.5176,
	0.7482,
	0.717,
	0.8367,
	0.7806,
	0.5533,
	0.9608,
	0.2035,
	0.8773,
	0.693,
	0.8415,
	0.6053,
	0.025,
	0.3273,
	0.2664,
	0.5094,
	0.1266,
	0.4979,
	0.4316,
	0.6516,
	0.6027,
	0.3366,
	0.4437,
	0.6694,
	0.2757,
	0.2482,
	0.3486,
	0.2093,
	0.4458,
	0.3572,
	0.7398,
	0.3901,
	0.5731,
	0.7213,
	0.8341,
	0.6622,
	0.3758,
	0.614,
	0.435,
	0.6216,
	0.4164,
	0.8865,
	0.299,
	0.6977,
	0.764,
	0.6526,
	0.7938,
	0.2086,
	0.74,
	0.1018,
	0.1279,
	0.8494,
	0.2405,
	0.4862,
	0.0838,
	0.6354,
	0.3063,
	0.9715,
	0.3772,
	0.5081,
	0.6239,
	0.306,
	0.0971,
	0.7794,
	0.7855,
	0.3258,
	0.9748,
	0.1608,
	0.5582,
	0.1715,
	0.9293,
	0.4131,
	0.3087,
	0.9843,
	0.4925,
	0.5804,
	0.4428,
	0.975,
	0.6459,
	0.8295,
	0.2375,
	0.279,
	0.06,
	0.7211,
	0.0217,
	0.1441,
	0.4326,
	0.0107,
	0.107,
	0.5953,
	0.7103,
	0.2331,
	0.876,
	0.4321,
	0.1851,
	0.7143,
	0.1114,
	0.0296,
	0.222,
	0.6745,
	0.0622,
	0.3832,
	0.4098,
	0.0383,
	0.9817,
	0.1401,
	0.2403,
	0.1944,
	0.7713,
	0.5733,
	0.6665,
	0.4671,
	0.9081,
	0.1087,
	0.4467,
	0.928,
	0.4759,
	0.6588,
	0.3357,
	0.0483,
	0.8823,
	0.9123,
	0.869,
	0.377,
	0.7624,
	0.8827,
	0.1157,
	0.379,
	0.3211,
	0.4421,
	0.3994,
	0.3878,
	0.6776,
	0.8661,
	0.9311,
	0.0993,
	0.3464,
	0.3156,
	0.654,
	0.9718,
	0.8414,
	0.7788,
	0.3982,
	0.9835,
	0.862,
	0.9579,
	0.0625,
	0.7859,
	0.3193,
	0.2385,
	0.945,
	0.8245,
	0.9568,
	0.0235,
	0.5615,
	0.5599,
	0.2642,
	0.2655,
	0.3078,
	0.0737,
	0.2351,
	0.7222,
	0.6295,
	0.048,
	0.6975,
	0.1338,
	0.2943,
	0.099,
	0.4487,
	0.2792,
	0.674,
	0.5778,
	0.5299,
	0.9511,
	0.6984,
	0.9623,
	0.3452,
	0.7752,
	0.4486,
	0.9764,
	0.6895,
	0.9283,
	0.7846,
	0.0635,
	0.3781,
	0.7371,
	0.4916,
	0.0489,
	0.0565,
	0.8802,
	0.9196,
	0.4415,
	0.0367,
	0.0662,
	0.787,
	0.1836,
	0.6732,
	0.6813,
	0.821,
	0.9267,
	0.3339,
	0.7163,
	0.4294,
	0.9366,
	0.6873,
	0.1227,
	0.6986,
	0.4325,
	0.7204,
	0.6862,
	0.6724,
	0.4076,
	0.9825,
	0.1193,
	0.5454,
	0.6863,
	0.0555,
	0.0706,
	0.7645,
	0.8981,
	0.933,
	0.0621,
	0.6544,
	0.8654,
	0.473,
	0.9979,
	0.1746,
	0.8867,
	0.3191,
	0.6191,
	0.8047,
	0.3755,
	0.0834,
	0.8193,
	0.7504,
	0.0596,
	0.7625,
	0.7574,
	0.3784,
	0.1606,
	0.05,
	0.8746,
	0.477,
	0.5511,
	0.5436,
	0.5242,
	0.0183,
	0.1554,
	0.7049,
	0.8623,
	0.9106,
	0.6324,
	0.6542,
	0.7114,
	0.0836,
	0.3207,
	0.5544,
	0.7216,
	0.2135,
	0.0274,
	0.5846,
	0.6493,
	0.8852,
	0.7024,
	0.7109,
	0.2782,
	0.9685,
	0.5119,
	0.0149,
	0.4889,
	0.9469,
	0.0294,
	0.7459,
	0.8356,
	0.1713,
	0.9528,
	0.9684,
	0.1788,
	0.7678,
	0.3484,
	0.181,
	0.5663,
	0.4843,
	0.0151,
	0.5653,
	0.953,
	0.0332,
	0.2025,
	0.3056,
	0.6254,
	0.6281,
	0.0134,
	0.7604,
	0.718,
	0.4616,
	0.0599,
	0.4318,
	0.6774,
	0.4835,
	0.489,
	0.21,
	0.6353,
	0.4234,
	0.1797,
	0.5099,
	0.293,
	0.081,
	0.8889,
	0.6515,
	0.8438,
	0.2426,
	0.2536,
	0.0147,
	0.2565,
	0.4317,
	0.8425,
	0.0847,
	0.5177,
	0.6028,
	0.11,
	0.7515,
	0.0172,
	0.4533,
	0.2563,
	0.5915,
	0.4261,
	0.51,
	0.911,
	0.8895,
	0.8744,
	0.6036,
	0.0502,
	0.3512,
	0.2332,
	0.2006,
	0.4915,
	0.267,
	0.6525,
	0.5368,
	0.4029,
	0.653,
	0.4559,
	0.2265,
	0.3757,
	0.6708,
	0.9592,
	0.6887,
	0.8794,
	0.8743,
	0.5202,
	0.2302,
	0.6517,
	0.6181,
	0.837,
	0.5583,
	0.7951,
	0.3614,
	0.7596,
	0.7334,
	0.2673,
	0.677,
	0.4938,
	0.1528,
	0.4631,
	0.4799,
	0.4945,
	0.7288,
	0.0146,
	0.3508,
	0.0561,
	0.9621,
	0.9712,
	0.0264,
	0.7826,
	0.0865,
	0.4416,
	0.3588,
	0.1094,
	0.4032,
	0.9805,
	0.4861,
	0.8896,
	0.3368,
	0.7271,
	0.4689,
	0.4906,
	0.3259,
	0.8652,
	0.8407,
	0.0873,
	0.3228,
	0.4144,
	0.8723,
	0.8594,
	0.5072,
	0.4456,
	0.5961,
	0.4221,
	0.8169,
	0.3394,
	0.8153,
	0.3865,
	0.7193,
	0.9336,
	0.3169,
	0.1343,
	0.8168,
	0.3852,
	0.0887,
	0.1003,
	0.895,
	0.6551,
	0.8916,
	0.6857,
	0.6943,
	0.324,
	0.6487,
	0.7309,
	0.5199,
	0.6148,
	0.8008,
	0.6307,
	0.1468,
	0.0055,
	0.3302,
	0.4508,
	0.6511,
	0.1425,
	0.6818,
	0.8484,
	0.1524,
	0.8496,
	0.398,
	0.1978,
	0.8216,
	0.4782,
	0.7332,
	0.7012,
	0.145,
	0.2529,
	0.149,
	0.8626,
	0.2417,
	0.8534,
	0.6602,
	0.1102,
	0.0581,
	0.0659,
	0.2395,
	0.088,
	0.7838,
	0.8995,
	0.2304,
	0.3449,
	0.605,
	0.3819,
	0.7609,
	0.1761,
	0.8105,
	0.144,
	0.2629,
	0.7863,
	0.3718,
	0.3459,
	0.102,
	0.1463,
	0.0685,
	0.5173,
	0.0374,
	0.6966,
	0.5295,
	0.0179,
	0.8545,
	0.5167,
	0.9587,
	0.3962,
	0.0245,
	0.0392,
	0.25,
	0.8701,
	0.4865,
	0.5104,
	0.0942,
	0.6265,
	0.3216,
	0.0035,
	0.3537,
	0.5718,
	0.5747,
	0.3276,
	0.4161,
	0.1549,
	0.3553,
	0.8201,
	0.2469,
	0.7738,
	0.5396,
	0.5594,
	0.8566,
	0.6114,
	0.5943,
	0.5201,
	0.0679,
	0.8345,
	0.0787,
	0.8899,
	0.988,
	0.5319,
	0.8546,
	0.1721,
	0.3511,
	0.0695,
	0.9644,
	0.3165,
	0.8481,
	0.609,
	0.6699,
	0.5524,
	0.6204,
	0.2005,
	0.7663,
	0.3625,
	0.166,
	0.9757,
	0.7527,
	0.7536,
	0.5184,
	0.9672,
	0.6262,
	0.8066,
	0.5311,
	0.0317,
	0.5168,
	0.0984,
	0.6433,
	0.5444,
	0.7416,
	0.8805,
	0.9361,
	0.9771,
	0.771,
	0.5664,
	0.5466,
	0.5393,
	0.3162,
	0.4597,
	0.7876,
	0.3386,
	0.8371,
	0.1906,
	0.1271,
	0.9704,
	0.331,
	0.3414,
	0.3304,
	0.9394,
	0.3593,
	0.3707,
	0.1605,
	0.741,
	0.0411,
	0.7662,
	0.7702,
	0.7699,
	0.3035,
	0.6971,
	0.462,
	0.4108,
	0.4432,
	0.1299,
	0.8098,
	0.6221,
	0.2826,
	0.7017,
	0.8499,
	0.7944,
	0.6013,
	0.5011,
	0.0052,
	0.0022,
	0.2589,
	0.6453,
	0.7879,
	0.2257,
	0.7592,
	0.5962,
	0.5803,
	0.8944,
	0.6466,
	0.7202,
	0.3027,
	0.0153,
	0.0405,
	0.5143,
	0.8657,
	0.2027,
	0.1393,
	0.6939,
	0.1734,
	0.7451,
	0.3485,
	0.9329,
	0.1178,
	0.0676,
	0.9582,
	0.7078,
	0.3021,
	0.5616,
	0.506,
	0.1887,
	0.8527,
	0.7907,
	0.1239,
	0.5193,
	0.4958,
	0.4212,
	0.7473,
	0.4573,
	0.3301,
	0.7922,
	0.0487,
	0.853,
	0.575,
	0.9666,
	0.5121,
	0.3019,
	0.6583,
	0.9422,
	0.1023,
	0.77,
	0.3939,
	0.5638,
	0.9242,
	0.8509,
	0.5975,
	0.8112,
	0.5873,
	0.3029,
	0.612,
	0.0388,
	0.4019,
	0.8447,
	0.5694,
	0.584,
	0.5031,
	0.9976,
	0.9003,
	0.2028,
	0.4001,
	0.5904,
	0.6877,
	0.5619,
	0.6438,
	0.119,
	0.1963,
	0.0255,
	0.3737,
	0.0626,
	0.767,
	0.3623,
	0.7443,
	0.2243,
	0.2967,
	0.9671,
	0.7733,
	0.425,
	0.5004,
	0.9869,
	0.7378,
	0.9207,
	0.2011,
	0.913,
	0.9435,
	0.0119,
	0.0998,
	0.5979,
	0.6721,
	0.3047,
	0.0412,
	0.7061,
	0.4743,
	0.2735,
	0.6084,
	0.3995,
	0.7854,
	0.6112,
	0.0874,
	0.1419,
	0.2397,
	0.2489,
	0.4704,
	0.8552,
	0.3422,
	0.0992,
	0.5771,
	0.2857,
	0.1812,
	0.5178,
	0.8361,
	0.6585,
	0.6592,
	0.9365,
	0.5704,
	0.734,
	0.5505,
	0.2574,
	0.9572,
	0.4907,
	0.1006,
	0.6002,
	0.948,
	0.0823,
	0.9977,
	0.2079,
	0.7006,
	0.9839,
	0.9952,
	0.4179,
	0.1493,
	0.3187,
	0.0495,
	0.6047,
	0.4259,
	0.2463,
	0.8565,
	0.494,
	0.3382,
	0.3705,
	0.3494,
	0.9643,
	0.1659,
	0.752,
	0.5283,
	0.3032,
	0.5337,
	0.2561,
	0.2844,
	0.1953,
	0.9079,
	0.4676,
	0.3082,
	0.3281,
	0.3514,
	0.3007,
	0.2601,
	0.7524,
	0.6035,
	0.2263,
	0.0404,
	0.2896,
	0.5878,
	0.4218,
	0.4397,
	0.5395,
	0.8664,
	0.2634,
	0.2763,
	0.126,
	0.3759,
	0.8036,
	0.5805,
	0.4742,
	0.8868,
	0.0949,
	0.6836,
	0.1543,
	0.9253,
	0.6334,
	0.4905,
	0.1845,
	0.8536,
	0.3594,
	0.304,
	0.7791,
	0.2953,
	0.2273,
	0.0995,
	0.9478,
	0.8269,
	0.7157,
	0.5719,
	0.2377,
	0.0556,
	0.611,
	0.7796,
	0.3842,
	0.1066,
	0.1568,
	0.3383,
	0.7418,
	0.4965,
	0.4256,
	0.9928,
	0.9342,
	0.5211,
	0.8949,
	0.4293,
	0.4876,
	0.9381,
	0.6379,
	0.2083,
	0.9489,
	0.5089,
	0.3551,
	0.5636,
	0.0444,
	0.0684,
	0.6371,
	0.1934,
	0.2107,
	0.1054,
	0.083,
	0.045,
	0.501,
	0.1813,
	0.0551,
	0.5541,
	0.9713,
	0.6327,
	0.3271,
	0.6449,
	0.2813,
	0.4632,
	0.1795,
	0.7362,
	0.5736,
	0.1592,
	0.2001,
	0.4271,
	0.0334,
	0.4224,
	0.5164,
	0.4459,
	0.2513,
	0.141,
	0.4074,
	0.7979,
	0.4737,
	0.3177,
	0.9538,
	0.2314,
	0.2224,
	0.38,
	0.3423,
	0.396,
	0.8396,
	0.8996,
	0.2153,
	0.5008,
	0.668,
	0.2212,
	0.4959,
	0.124,
	0.9683,
	0.9152,
	0.0697,
	0.3872,
	0.2249,
	0.8329,
	0.9532,
	0.5086,
	0.284,
	0.3918,
	0.8533,
	0.2124,
	0.9563,
	0.5355,
	0.5984,
	0.0941,
	0.2587,
	0.7083,
	0.4273,
	0.7675,
	0.0157,
	0.5922,
	0.811,
	0.7795,
	0.7002,
	0.8923,
	0.2367,
	0.3895,
	0.5358,
	0.4762,
	0.4205,
	0.3473,
	0.7631,
	0.3181,
	0.4484,
	0.4866,
	0.1331,
	0.4013,
	0.3219,
	0.7304,
	0.6271,
	0.024,
	0.162,
	0.7853,
	0.7009,
	0.7052,
	0.5866,
	0.0598,
	0.6935,
	0.5294,
	0.7412,
	0.2088,
	0.2899,
	0.536,
	0.8864,
	0.7754,
	0.186,
	0.6236,
	0.8678,
	0.6409,
	0.2724,
	0.6499,
	0.3835,
	0.1374,
	0.3771,
	0.485,
	0.1876,
	0.2467,
	0.3766,
	0.529,
	0.1482,
	0.8714,
	0.8456,
	0.276,
	0.4947,
	0.7079,
	0.1895,
	0.3463,
	0.3959,
	0.059,
	0.5288,
	0.5973,
	0.9565,
	0.0007,
	0.1819,
	0.5726,
	0.725,
	0.8615,
	0.9597,
	0.5341,
	0.4791,
	0.0637,
	0.7189,
	0.8377,
	0.2996,
	0.4116,
	0.7513,
	0.447,
	0.9642,
	0.6199,
	0.7126,
	0.9424,
	0.1926,
	0.3889,
	0.4005,
	0.2955,
	0.3316,
	0.3658,
	0.5079,
	0.1505,
	0.4664,
	0.6769,
	0.9013,
	0.4662,
	0.9385,
	0.919,
	0.4329,
	0.1386,
	0.441,
	0.1573,
	0.9432,
	0.2215,
	0.4675,
	0.6082,
	0.2171,
	0.0601,
	0.5813,
	0.0064,
	0.3498,
	0.5191,
	0.8051,
	0.7468,
	0.4518,
	0.4798,
	0.5807,
	0.5956,
	0.2271,
	0.1947,
	0.3702,
	0.9334,
	0.6115,
	0.6521,
	0.0968,
	0.9732,
	0.9117,
	0.1679,
	0.4137,
	0.3306,
	0.6954,
	0.6759,
	0.0491,
	0.439,
	0.1821,
	0.6581,
	0.62,
	0.0725,
	0.282,
	0.7384,
	0.2225,
	0.1128,
	0.3438,
	0.6974,
	0.6567,
	0.7995,
	0.9058,
	0.6223,
	0.8606,
	0.57,
	0.5271,
	0.1725,
	0.0423,
	0.8813,
	0.3132,
	0.3989
};
